
Free Information Xchange '98 presents:

Mortal Kombat 4 - CD crack by Static Vengeance

Requirements:
Hex editor and full game install
W32Dasm if you wish to follow along

	So you want to learn to crack CD checks, do you?  Alright, let's look at one type of CD check
that'll take some digging and some (did I say "some" read that as a "ton of") manual work.  The reason
I bring it up as some CD checks are a lot more work and not being the most fluent in X86 assembly
language I did it the old fasion way.  Brute force traking down with a little help from W32Dasm from
RUSoft.  Anyways, first things first... The usual aproch:  disassemble the exe file with W32Dasm.  Then
look for the tell tale signs of copy protection.  My favorite method is to go up to the menu and select
"Refs" and the select "String data references" and look for things like "Please Insert the CD", the volume
name of the CD, "C:\" or things like that.  But with MK4 there are none of the common tell tale strings
to double click on.  So plan 2 involves looking for the KERNEL32 call "GetDriveTypeA".  To find out if
this call was used in the program check in the disassembled listing, you would see something like this:

+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++

   Import Module 001: KERNEL32.dll
 Addr:xxxxxxxx hint(xxxx) Name: ?????????????
   ---  Many more calls listed  ---
 Addr:000D3BBE hint(00DF) Name: GetDriveTypeA
   ---  Many more calls listed  ---

	Well, it is used so you'll need to use the text string search to find it in the disassebly code.
after checking around and making an edit.  I ran the game and realized I had eliminated the cut scenes
and intros but NOT the copy protection.  So this leaves the last choice and that is calls through WINMM.
much like the KERNEL32.dll, the WINMM.dll would show up like this:

   Import Module 005: WINMM.dll

 Addr:000D410E hint(001A) Name: joyGetDevCapsA
 Addr:000D414C hint(0094) Name: timeEndPeriod
 Addr:000D413A hint(0093) Name: timeBeginPeriod
 Addr:000D412C hint(001E) Name: joyGetPosEx
 Addr:000D4120 hint(001D) Name: joyGetPos
 Addr:000D40FE hint(0017) Name: auxSetVolume
 Addr:000D40EE hint(0014) Name: auxGetNumDevs
 Addr:000D40DC hint(0012) Name: auxGetDevCapsA
 Addr:000D40CC hint(0015) Name: auxGetVolume
 Addr:000D40BE hint(0097) Name: timeGetTime
 Addr:000D40AC hint(0032) Name: mciSendCommandA

	It's the last call we are interested in, it's the mciSendCommandA call that is used to operate
the CD for music.  However if a status call comes back with an error, then there's no CD in the drive.
The program can check the track length and other things that will tell the program that the original CD
is present.  So we need to do a text string search for "mciSendCommandA"  Doing so, you'll end up at this
section of code with the first sequence of your search word:

* Referenced by a CALL at Addresses:
|:004AC333   , :004AC385   , :004AC4B9   , :004AC51C   , :004AC58C   <-- 9 Sections of code to check
|:004AC61F   , :004AC73B   , :004AC926   , :004C3EFE   
|
:004AC2B0 A180185400              mov eax, dword ptr [00541880]
:004AC2B5 83EC24                  sub esp, 00000024
:004AC2B8 85C0                    test eax, eax
:004AC2BA 56                      push esi

* Reference To: WINMM.mciSendCommandA, Ord:0032h                     <-- Text string that got us here
                                  |
:004AC2BB 8B353C024D00            mov esi, dword ptr [004D023C]
:004AC2C1 7531                    jne 004AC2F4
:004AC2C3 8D442414                lea eax, dword ptr [esp+14]

* Possible StringData Ref from Data Obj ->"cdaudio"                 <-- Deals with the CD
                                  |
:004AC2C7 C744241C84264F00        mov [esp+1C], 004F2684
:004AC2CF 50                      push eax
:004AC2D0 6800210000              push 00002100
:004AC2D5 6803080000              push 00000803
:004AC2DA 6A00                    push 00000000
:004AC2DC FFD6                    call esi
:004AC2DE F7D8                    neg eax
:004AC2E0 1BC0                    sbb eax, eax
:004AC2E2 40                      inc eax
:004AC2E3 A380185400              mov dword ptr [00541880], eax
:004AC2E8 743F                    je 004AC329
:004AC2EA 8B4C2418                mov ecx, dword ptr [esp+18]
:004AC2EE 890D60185400            mov dword ptr [00541860], ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004AC2C1(C)
|
:004AC2F4 A160185400              mov eax, dword ptr [00541860]
:004AC2F9 8D542404                lea edx, dword ptr [esp+04]
:004AC2FD 52                      push edx
:004AC2FE 6800010000              push 00000100
:004AC303 6814080000              push 00000814
:004AC308 50                      push eax
:004AC309 C744241C05000000        mov [esp+1C], 00000005
:004AC311 FFD6                    call esi
:004AC313 85C0                    test eax, eax
:004AC315 7512                    jne 004AC329
:004AC317 8B442408                mov eax, dword ptr [esp+08]
:004AC31B 85C0                    test eax, eax
:004AC31D 740A                    je 004AC329                     <-- Zero here means error on command
:004AC31F B801000000              mov eax, 00000001               <-- Otherwise a non-zero is saved in
:004AC324 5E                      pop esi                         <--  in eax for a "good" result
:004AC325 83C424                  add esp, 00000024
:004AC328 C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004AC2E8(C), :004AC315(C), :004AC31D(C)
|
:004AC329 33C0                    xor eax, eax                    <-- Redundant, but make sure eax = zero
:004AC32B 5E                      pop esi
:004AC32C 83C424                  add esp, 00000024
:004AC32F C3                      ret

	Just to test to make sure this bit of code is used for the CD check I changed the loading
of eax with 00000001 to mov eax, 00000000 which forces an error.  Then I ran the game with the CD
in my CD rom drive to test the results.  Sure enough the game came up and asks for the original
CD!  So now we need to narrow it down and the elimenate the CD check totally.  So checking through
the first call resulted in nothing useful.  So I checked into the second call and found this:

* Referenced by a CALL at Address:
|:004C3F1B                                                 <-- Where it was called from
|
:004AC380 83EC1C                  sub esp, 0000001C
:004AC383 56                      push esi
:004AC384 57                      push edi
:004AC385 E826FFFFFF              call 004AC2B0
:004AC38A 85C0                    test eax, eax
:004AC38C 0F84A3000000            je 004AC435
:004AC392 8B0D60185400            mov ecx, dword ptr [00541860]
:004AC398 8B7C2428                mov edi, dword ptr [esp+28]

* Reference To: WINMM.mciSendCommandA, Ord:0032h           <-- Another WINMM call
                                  |
:004AC39C 8B353C024D00            mov esi, dword ptr [004D023C]
:004AC3A2 8D442414                lea eax, dword ptr [esp+14]
:004AC3A6 50                      push eax
:004AC3A7 6810010000              push 00000110
:004AC3AC 6814080000              push 00000814
:004AC3B1 51                      push ecx
:004AC3B2 C744242C01400000        mov [esp+2C], 00004001
:004AC3BA 897C2430                mov dword ptr [esp+30], edi
:004AC3BE FFD6                    call esi
:004AC3C0 85C0                    test eax, eax
:004AC3C2 7571                    jne 004AC435
:004AC3C4 817C241840040000        cmp dword ptr [esp+18], 00000440
:004AC3CC 7567                    jne 004AC435
:004AC3CE A160185400              mov eax, dword ptr [00541860]
:004AC3D3 8D542408                lea edx, dword ptr [esp+08]
:004AC3D7 52                      push edx
:004AC3D8 6800040000              push 00000400
:004AC3DD 680D080000              push 0000080D
:004AC3E2 50                      push eax
:004AC3E3 C744241C02000000        mov [esp+1C], 00000002
:004AC3EB FFD6                    call esi
:004AC3ED 8B1560185400            mov edx, dword ptr [00541860]
:004AC3F3 8D4C2414                lea ecx, dword ptr [esp+14]
:004AC3F7 51                      push ecx
:004AC3F8 6810010000              push 00000110
:004AC3FD 6814080000              push 00000814
:004AC402 52                      push edx
:004AC403 C744242C01000000        mov [esp+2C], 00000001
:004AC40B 897C2430                mov dword ptr [esp+30], edi
:004AC40F FFD6                    call esi
:004AC411 85C0                    test eax, eax
:004AC413 7520                    jne 004AC435
:004AC415 8B442418                mov eax, dword ptr [esp+18]
:004AC419 33C9                    xor ecx, ecx
:004AC41B 8ACC                    mov cl, ah
:004AC41D 25FF000000              and eax, 000000FF
:004AC422 8D0440                  lea eax, dword ptr [eax+2*eax]
:004AC425 8D1480                  lea edx, dword ptr [eax+4*eax]
:004AC428 C1E202                  shl edx, 02
:004AC42B 03CA                    add ecx, edx
:004AC42D 8BC1                    mov eax, ecx
:004AC42F 5F                      pop edi
:004AC430 5E                      pop esi
:004AC431 83C41C                  add esp, 0000001C
:004AC434 C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004AC38C(C), :004AC3C2(C), :004AC3CC(C), :004AC413(C)
|
:004AC435 5F                      pop edi
:004AC436 33C0                    xor eax, eax
:004AC438 5E                      pop esi
:004AC439 83C41C                  add esp, 0000001C
:004AC43C C3                      ret

	So I started with an unmodified version of the MK4 exe file and changed the conditional
jump at 4AC38C to normal jump.  Then I reran the MK4 and it asked for the CD again so we now
know we're on the right track.  So lets trace this routine back to it's caller and check that
code.

* Referenced by a CALL at Addresses:
|:004B1B78   , :004B8248   
|
:004C3EA0 83EC3C                  sub esp, 0000003C
:004C3EA3 56                      push esi
:004C3EA4 33C9                    xor ecx, ecx                  <-- ecx is zero'ed out here
:004C3EA6 B85C000000              mov eax, 0000005C
:004C3EAB 57                      push edi
:004C3EAC 894C2408                mov dword ptr [esp+08], ecx   <-- Set up many variables
:004C3EB0 8944240C                mov dword ptr [esp+0C], eax
:004C3EB4 89442410                mov dword ptr [esp+10], eax
:004C3EB8 89442414                mov dword ptr [esp+14], eax
:004C3EBC 89442418                mov dword ptr [esp+18], eax
:004C3EC0 8944241C                mov dword ptr [esp+1C], eax
:004C3EC4 89442420                mov dword ptr [esp+20], eax
:004C3EC8 89442424                mov dword ptr [esp+24], eax
:004C3ECC C74424287A000000        mov [esp+28], 0000007A
:004C3ED4 C744242C10000000        mov [esp+2C], 00000010
:004C3EDC C744243038000000        mov [esp+30], 00000038
:004C3EE4 89442434                mov dword ptr [esp+34], eax
:004C3EE8 89442438                mov dword ptr [esp+38], eax
:004C3EEC 8944243C                mov dword ptr [esp+3C], eax
:004C3EF0 C74424405A000000        mov [esp+40], 0000005A
:004C3EF8 890DFCDC4F00            mov dword ptr [004FDCFC], ecx  <-- Store a zero here
:004C3EFE E8AD83FEFF              call 004AC2B0
:004C3F03 85C0                    test eax, eax
:004C3F05 743E                    je 004C3F45
:004C3F07 E82484FEFF              call 004AC330
:004C3F0C 83F80F                  cmp eax, 0000000F
:004C3F0F 7534                    jne 004C3F45
:004C3F11 BE01000000              mov esi, 00000001
:004C3F16 8D7C240C                lea edi, dword ptr [esp+0C]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004C3F39(C)
|
:004C3F1A 56                      push esi
:004C3F1B E86084FEFF              call 004AC380                  <-- Call the above CD audio check
:004C3F20 8B57FC                  mov edx, dword ptr [edi-04]
:004C3F23 83C404                  add esp, 00000004
:004C3F26 2BC2                    sub eax, edx
:004C3F28 99                      cdq
:004C3F29 33C2                    xor eax, edx
:004C3F2B 2BC2                    sub eax, edx
:004C3F2D 83F805                  cmp eax, 00000005
:004C3F30 7F13                    jg 004C3F45
:004C3F32 46                      inc esi
:004C3F33 83C704                  add edi, 00000004
:004C3F36 83FE0F                  cmp esi, 0000000F
:004C3F39 7EDF                    jle 004C3F1A                        <-- Compare and the possibly jump
:004C3F3B C705FCDC4F0001000000    mov dword ptr [004FDCFC], 00000001  <-- Store a 01 when it was initialized
                                                                      <--  with a 00, could be some type of
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: <--  flag variable used later
|:004C3F05(C), :004C3F0F(C), :004C3F30(C)
|
:004C3F45 5F                      pop edi
:004C3F46 5E                      pop esi
:004C3F47 83C43C                  add esp, 0000003C
:004C3F4A C3                      ret

	In my work cracking CD checks, I have come to notice things like clearing a location then
further down in the code setting it to a different value right after a condition jump.  More times
then not this is setting a "flag" to a fail value, making the test for the CD then if the test passes
set the flag to a "pass" value.  Okay, let's go back one more step and look at that code:

:004B1B6E E89DE1F6FF              call 0041FD10
:004B1B73 E8A82CFBFF              call 00464820
:004B1B78 E823230100              call 004C3EA0                  <-- Call the routine to check for the CD
:004B1B7D A1FCDC4F00              mov eax, dword ptr [004FDCFC]  <-- Check the "flag" value
:004B1B82 85C0                    test eax, eax
:004B1B84 750A                    jne 004B1B90                   <-- Anything but 01 passes
:004B1B86 6A07                    push 00000007
:004B1B88 E8B33B0000              call 004B5740                  <-- Do the sword sound & ask for the CD
:004B1B8D 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B1B84(C)
|
:004B1B90 C3                      ret

	Okay, from here I started with a clean (unmodified) copy of the MK4 exe and NOP'ed the
conditional jump at 4B1B84 and ran the game with the CD in the drive.  Sure enough I head the
"double sword slash" sound and it asked for the CD.  So we know the CD check is at 4C3EA0 and
is called from 4B1B78 and 4B8248.  From here, search the MK4 exe file for E8 23 23 01 00 and
overwite it with B8 01 00 00 00 (mov eax, 00000001).  Then search for the other call to the CD
check (E8 53 BC 00 00) and do the same.  You'll have a cracked copy of Mortal Kombat 4 you can
play from your hard drive.

	Midway released an updated version of Mortal Kombat 4 that has better support for Win98
and DirectX6 (which means they fixxed some program BUGS).  So I downloaded that file and did
the same type of thing as I did above and found the two calls the CD check.  I made the same
type of patches:

:004B2618 E8F3D6F6FF              call 0041FD10
:004B261D E80E22FBFF              call 00464830
:004B2622 E8C92B0100              call 004C51F0                  <-- Do the CD check
:004B2627 39357CFD4F00            cmp dword ptr [004FFD7C], esi  <-- Test the flag, esi=00
:004B262D 750A                    jne 004B2639                   <-- If not equal jump over asking for CD
:004B262F 6A07                    push 00000007
:004B2631 E80A3D0000              call 004B6340                  <-- Sword sounds & ask for the CD
:004B2636 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B262D(C)
|
:004B2639 893520F97A00            mov dword ptr [007AF920], esi
:004B263F 89351CF97A00            mov dword ptr [007AF91C], esi  <-- Zero out CRC flag
:004B2645 E816A4FFFF              call 004ACA60                  <-- Remember this call for later!!!
:004B264A 85C0                    test eax, eax
:004B264C 7430                    je 004B267E

* Reference To: WINMM.timeGetTime, Ord:0097h
                                  |
:004B264E FF1540224D00            Call dword ptr [004D2240]
:004B2654 50                      push eax
:004B2655 E8A63E0100              call 004C6500
:004B265A 83C404                  add esp, 00000004
:004B265D E8AE3E0100              call 004C6510
:004B2662 A803                    test al, 03
:004B2664 7409                    je 004B266F
:004B2666 893D20F97A00            mov dword ptr [007AF920], edi
:004B266C 5F                      pop edi
:004B266D 5E                      pop esi
:004B266E C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B2664(C)
|
:004B266F E89C3E0100              call 004C6510
:004B2674 0D81180000              or eax, 00001881               <-- OR the results with 00001881
:004B2679 A31CF97A00              mov dword ptr [007AF91C], eax  <-- 7AF91C must equal zero to play!

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B264C(C)
|
:004B267E 5F                      pop edi
:004B267F 5E                      pop esi
:004B2680 C3                      ret

	It worked, sort of.  You just cannot move left in any portion of the game, either with your
fighter or on the menu selections.  Well, there must be some type of secondary copy protection.
So I checked the disassembley and found some "filler" bytes (IE: bytes used so routines start on
even memory locations like 41FD10 istead of 41FD1x where x is 1 to 9), in this case 90's are used
for the filler.  So I picked one and changed it to a 91 and ran the game with the CD in the drive.
The game started up like normal and didn't ask for the CD or anything funny, except I couldn't
move left!  So Midway has added a CRC (or some type of checksum) check to the game.  Once again,
back to some old fasion manual work to track it down.  I have never had to track down a checksum
check before so I had to find some where to start.  I thought as long as the program had to run a
checksum on itself it would need to read the exe file off the hard drive.  And I know to do that
you need to use the "rb" (read binary?) call.  So I went up to the REFS menu and selected "String
data references" and from the pop up box I scrolled down to "rb" and double clicked it and checked
the code around it and I came across this:

* Referenced by a CALL at Address:
|:004ACA92                                           <-- Where it was called from
|
:004ACAE0 B810400000              mov eax, 00004010
:004ACAE5 E8E6920100              call 004C5DD0
:004ACAEA 8B842414400000          mov eax, dword ptr [esp+00004014]
:004ACAF1 53                      push ebx
:004ACAF2 55                      push ebp
:004ACAF3 56                      push esi
:004ACAF4 57                      push edi

* Possible StringData Ref from Data Obj ->"rb"       <-- what got use here, a "read binary" call
                                  |
:004ACAF5 685C504D00              push 004D505C
:004ACAFA 50                      push eax
:004ACAFB E8B0920100              call 004C5DB0
:004ACB00 8BD8                    mov ebx, eax
:004ACB02 83C408                  add esp, 00000008
:004ACB05 85DB                    test ebx, ebx
:004ACB07 7510                    jne 004ACB19
:004ACB09 B8FEFFFFFF              mov eax, FFFFFFFE
:004ACB0E 5F                      pop edi
:004ACB0F 5E                      pop esi
:004ACB10 5D                      pop ebp
:004ACB11 5B                      pop ebx
:004ACB12 81C410400000            add esp, 00004010
:004ACB18 C3                      ret

	From here we need to go back to the caller to see if it has anything to do with the copy
protection.  So let's check out the code and routine around 4ACA92 to see what it does:

* Referenced by a CALL at Address:
|:004B2645                                            <-- Where it was called from
|
:004ACA60 81EC00040000            sub esp, 00000400
:004ACA66 8D442400                lea eax, dword ptr [esp]
:004ACA6A 6800040000              push 00000400
:004ACA6F 50                      push eax
:004ACA70 6A00                    push 00000000

* Reference To: KERNEL32.GetModuleHandleA, Ord:00FEh
                                  |
:004ACA72 FF152C214D00            Call dword ptr [004D212C]
:004ACA78 50                      push eax

* Reference To: KERNEL32.GetModuleFileNameA, Ord:00FCh          <-- Checking name of the exe file?!?
                                  |
:004ACA79 FF15A0204D00            Call dword ptr [004D20A0]
:004ACA7F 85C0                    test eax, eax
:004ACA81 750A                    jne 004ACA8D
:004ACA83 83C8FF                  or eax, FFFFFFFF
:004ACA86 81C400040000            add esp, 00000400
:004ACA8C C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACA81(C)                                                          <-- Conditional jump down to here
|
:004ACA8D 8D4C2400                lea ecx, dword ptr [esp]
:004ACA91 51                      push ecx
:004ACA92 E849000000              call 004ACAE0            <-- The call to the "rb" call
:004ACA97 83C404                  add esp, 00000004
:004ACA9A 85C0                    test eax, eax
:004ACA9C 752C                    jne 004ACACA
:004ACA9E 8B1520395400            mov edx, dword ptr [00543920]
:004ACAA4 A198464F00              mov eax, dword ptr [004F4698]
:004ACAA9 3BD0                    cmp edx, eax
:004ACAAB 750F                    jne 004ACABC
:004ACAAD A124395400              mov eax, dword ptr [00543924]
:004ACAB2 8B0D9C464F00            mov ecx, dword ptr [004F469C]
:004ACAB8 3BC1                    cmp eax, ecx
:004ACABA 740C                    je 004ACAC8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACAAB(C)
|
:004ACABC B8F6FFFFFF              mov eax, FFFFFFF6                 <-- Multiple exits and exit values!
:004ACAC1 81C400040000            add esp, 00000400
:004ACAC7 C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACABA(C)
|
:004ACAC8 33C0                    xor eax, eax                      <-- Multiple exits and exit values!

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004ACA9C(C)
|
:004ACACA 81C400040000            add esp, 00000400
:004ACAD0 C3  

	To me, this section of code is looking good for being the culprit.  It's doing some KERNEL32
calls and getting the module file name.  That sounds like it's getting the name the exe file that was
run, right?  So let's go back to the call at 4B2645 and check it out:

:004B2618 E8F3D6F6FF              call 0041FD10
:004B261D E80E22FBFF              call 00464830
:004B2622 E8C92B0100              call 004C51F0                  <-- Do the CD check
:004B2627 39357CFD4F00            cmp dword ptr [004FFD7C], esi  <-- Test the flag
:004B262D 750A                    jne 004B2639                   <-- If not equal jump over asking for CD
:004B262F 6A07                    push 00000007
:004B2631 E80A3D0000              call 004B6340                  <-- Sword sounds & ask for the CD
:004B2636 83C404                  add esp, 00000004

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B262D(C)
|
:004B2639 893520F97A00            mov dword ptr [007AF920], esi
:004B263F 89351CF97A00            mov dword ptr [007AF91C], esi
:004B2645 E816A4FFFF              call 004ACA60                  <-- Read the exe file!
:004B264A 85C0                    test eax, eax                  <-- Check the returned value
:004B264C 7430                    je 004B267E                    <-- Need to take this jump

* Reference To: WINMM.timeGetTime, Ord:0097h
                                  |
:004B264E FF1540224D00            Call dword ptr [004D2240]
:004B2654 50                      push eax
:004B2655 E8A63E0100              call 004C6500
:004B265A 83C404                  add esp, 00000004
:004B265D E8AE3E0100              call 004C6510
:004B2662 A803                    test al, 03
:004B2664 7409                    je 004B266F
:004B2666 893D20F97A00            mov dword ptr [007AF920], edi
:004B266C 5F                      pop edi
:004B266D 5E                      pop esi
:004B266E C3                      ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B2664(C)
|
:004B266F E89C3E0100              call 004C6510                 <-- Do a checksum
:004B2674 0D81180000              or eax, 00001881              <-- or the result with the actual checksum
:004B2679 A31CF97A00              mov dword ptr [007AF91C], eax <-- store it here

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B264C(C)
|
:004B267E 5F                      pop edi
:004B267F 5E                      pop esi
:004B2680 C3                      ret

	Well we ended up right back to the code that checks for the CD!  Then the above routine
does a checksum on the exe to see if we tried to crack it.  So, the only thing left to do with
this newly updated MK4 off the net is to make the actual edits to the Mortal Kombat 4.exe file.
As you already know changing the two calls to the CD check with mov eax, 00000001 FiX'es the
actual check.  However with the checksumming code I changed the first call (call 004ACA60) to
xor eax, eax and filled in the rest with NOP's.  This efectivly forces the je jump at 4B264C to
always be taken which allows you to play a fully functional game of MK4 without the CD.  Follow
these steps to produce a cracked copy of MK4 (by version):

1.  Do a normal install of the game (2 files copied)
2.  Copy all files from the "DATA" directory from the MK4 CD
    into the same place you installed MK4 (except mk4.exe)
3.  Edit Mortal Kombat 4.exe
    ==============================================
    Search for: E8 23 23 01 00  at offset 724,856
    Change to : B8 01 00 00 00

    Search for: E8 53 BC 00 00  at offset 751,176
    Change to : B8 01 00 00 00

    Edit Mortal Kombat 4.exe from mk4patch1.zip off the net
    ==============================================
    Search for: E8 C9 2B 01 00  at offset 727,586
    Change to : B8 01 00 00 00

    Search for: E8 16 A4 FF FF  at offset 727,621
    Change to : 33 C0 90 90 90

    Search for: E8 83 C3 00 00  at offset 754,280
    Change to : B8 01 00 00 00

    Edit Mortal Kombat 4.exe from mk4patch3.zip off the net
    ==============================================
    Search for: E8 C9 2B 01 00  at offset 727,650
    Change to : B8 01 00 00 00

    Search for: E8 D6 A3 FF FF  at offset 727,685
    Change to : 33 C0 90 90 90

    Search for: E8 83 C3 00 00  at offset 754,344
    Change to : B8 01 00 00 00


	That's it, after copying the files and making the above edit you'll have a copy of Mortal
Kombat 4 that runs off your hard drive and you don't have to dig out the original MK4 CD to play
it.  Becuase this one has been FiX'ed

Static Vengeance

NOTE: When the game installs, it copies MK4.EXE off the CD and renames it to Mortal Kombat 4.exe
therefore you do not need it to run the game as it is already there... just renamed.

NOTE2:  The URL for the MK4 patch is:  http://www.midway.com/home/mk4/mk4patch3.zip
